/* QtLua -- Lua bindings for Qt
   Copyright (C) 2011, Jarek Pelczar

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 3 of the License, or (at your option) any later version.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General
   Public License along with this library; if not, write to the
   Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
   Boston, MA 02110-1301 USA

*/

#ifndef QLUASCRIPTENGINE_P_H
#define QLUASCRIPTENGINE_P_H

#include "qluascriptengine.h"
#include "qlualinkedlist_p.h"
#include "../etc/lua.hpp"
#include "qluaglobal.h"
#include "qluascriptprogram.h"
#include "qluaexception.h"
#include <QDebug>
#include <QMetaProperty>

class QLuaScriptContext;
class QLuaScriptEngineAgentPrivate;

class QLuaScriptEnginePrivate
{
    Q_DECLARE_PUBLIC(QLuaScriptEngine)
public:
    QLuaScriptEngine * q_ptr;
    lua_State * L;
#ifdef QT_DEBUG
    QHash<void *, int> m_allocedPtrs;
#endif
    QLuaInternal::QLinkedListNode m_values;
    QLuaScriptContext * m_rootContext;
    QLuaScriptContext * m_currentContext;
    QHash<int, QLuaInternal::QLuaMetaTypeRegistryEntry *> m_metaRegistry;
    QHash<void *, int> m_ptrMetaTypes;
    QSet<QObject *> m_wrappedObjects;
    QLuaScriptValue m_weakRefsTable;
    bool m_dtorPending;
    QLuaScriptEngineAgentPrivate * m_debugger;
    QHash<qint64, QLuaScriptProgram> m_programs;
    QHash<QByteArray, qint64> m_fileNameToProgramId;
    qint64 m_lastScriptId;
    bool m_gcForced;
    QLuaException m_lastException;

    QLuaScriptEnginePrivate();
    ~QLuaScriptEnginePrivate();

    void init();
    void loadPlugins();

    bool fileNameIsPlugin(const QString& str);

    static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize);
    static int l_panic (lua_State *L);

    static inline QLuaScriptEnginePrivate * priv(QLuaScriptEngine * ptr) {
        return ptr->d_ptr;
    }

    int do_call(int narg, int nclean);
    static int invoke_traceback(lua_State * L);

    void _q_objectDestroyed(QObject *);

    bool convertScriptValueToPropertyType(bool flagsOrEnum, int userType, const QLuaScriptValue& value, QVariant& result);

    bool scriptConnect(QObject * sender, const char * signal,
                       QLuaScriptValue receiver, QLuaScriptValue function,
                       Qt::ConnectionType type);

    bool scriptDisconnect(QObject * sender, const char * signal,
                          QLuaScriptValue receiver, QLuaScriptValue function);


    bool scriptConnect(QObject * sender, int signalIndex,
                       QLuaScriptValue receiver, QLuaScriptValue function,
                       QLuaScriptValue senderWrapper,
                       Qt::ConnectionType type);

    bool scriptDisconnect(QObject * sender, int signalIndex,
                          QLuaScriptValue receiver, QLuaScriptValue function);

    bool scriptConnect(QLuaScriptValue signal, QLuaScriptValue receiver,
                       QLuaScriptValue function, Qt::ConnectionType type);

    bool scriptDisconnect(QLuaScriptValue signal, QLuaScriptValue receiver,
                       QLuaScriptValue function);

    static void debug_hook(lua_State *L, lua_Debug *ar);
    static void context_hook(lua_State *L, lua_Debug *ar);

    void dispatchCallEnter(lua_Debug * ar, bool use_agent);
    void dispatchCallExit(lua_Debug * ar, bool use_agent);
};

#endif // QLUASCRIPTENGINE_P_H
